/*
 * #%L
 * Server
 * %%
 * Copyright (C) 2011 Ractoc.com
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */
package com.ractoc.opengamefinder.server.plugins;

import org.apache.log4j.Logger;

import com.ractoc.opengamefinder.api.results.MessageResultsErrorCodes;
import com.ractoc.opengamefinder.api.messages.NetworkMessage;
import com.ractoc.opengamefinder.api.results.NetworkMessageResult;
import com.ractoc.opengamefinder.server.plugins.messages.ServerMessage;
import com.ractoc.opengamefinder.server.plugins.messages.StoreSessionValueMessage;
import com.ractoc.pffj.api.BasePlugin;
import com.ractoc.pffj.api.BasePluginMessage;
import com.ractoc.pffj.api.BasePluginMessageResult;
import com.ractoc.pffj.api.PluginMessage;
import com.ractoc.pffj.api.PluginMessageResultListener;
import com.ractoc.pffj.core.PluginController;
import com.ractoc.pffj.core.PluginException;

/**
 * Base server plugin class, contains all the methods all the other plugin
 * classes have in common.
 * 
 * @author ractoc
 * @version 0.1
 */
public abstract class BaseServerPlugin extends BasePlugin {

    private static Logger logger = Logger.getLogger(BaseServerPlugin.class.getName());

    /**
     * The session id related to the current ServerMessage.
     */
    protected Integer sessionId;

    /**
     * instead of overriding this method, all classes extending BaseServerPlugin
     * should override the processServerMessage method instead.
     * 
     * {@inheritDoc}
     */
    @Override
    public final void processMessage(final PluginMessage msg, final PluginMessageResultListener listener) {
        final ServerMessage sMsg = (ServerMessage) msg;
        sessionId = sMsg.getSessionId();
        processServerMessage(sMsg.getPayload(), listener);
    }

    /**
     * This method is called when this Plugin needs to process the received
     * PluginMessage. This method replaces the use of the processMessage method.
     * 
     * @param msg
     *            The message to process.
     * @param listener
     *            The listener that wants to be notified of the
     *            {@link com.ractoc.pffj.api.BasePluginMessageResult} returned
     *            by the plugin.
     * @see PluginMessage
     * @see BasePluginMessageResult
     */
    public abstract void processServerMessage(PluginMessage msg, PluginMessageResultListener listener);

    /**
     * Send a message via the network to the client.
     * 
     * @param result
     *            The result of the message sent.
     * @param msg
     *            The message to sent.
     * @param originPlugin
     *            The plugin the message came from.
     * @param destinationPlugin
     *            The plugin on the client the message is intended for.
     * @param secure
     *            Is the transfer to be secure?
     * @param reliable
     *            Is the transfer to be reliable?
     * @param playerId
     *            The player ID from the player sending the message.
     */
    protected final void sendNetworkMessage(final BasePluginMessageResult result, final BasePluginMessage msg,
            final String originPlugin, final String destinationPlugin, final boolean secure, final boolean reliable,
            final int playerId) {
        final NetworkMessage nMsg = new NetworkMessage();
        nMsg.setPayload(msg);
        nMsg.setOriginPlugin(originPlugin);
        nMsg.setDestinationPlugin(destinationPlugin);
        nMsg.setSecure(secure);
        nMsg.setReliable(reliable);
        nMsg.setPlayerId(playerId);
        NetworkMessageResult nResult = null;
        try {
            nResult = (NetworkMessageResult) PluginController.getCurrentPluginController().processMessage(
                    "networkPlugin", nMsg);
        } catch (final PluginException e) {
            result.setErrorCode(MessageResultsErrorCodes.INTERNAL_ERROR);
            logger.error("Error sending message through the plugin system: ", e);
        }
        if (nResult.getErrorCode() != MessageResultsErrorCodes.SUCCESS) {
            result.setErrorCode(nResult.getErrorCode());
        } else {
            result.setErrorCode(MessageResultsErrorCodes.SUCCESS);
        }
    }

    /**
     * Store the supplied key-value in the current session.
     * 
     * @param key
     *            The key with which to register the value in the session for
     *            later retrieval.
     * @param value
     *            The value to staore in the current session.
     */
    public final void storeSessionValue(final String key, final Object value) {
        final StoreSessionValueMessage ssvMsg = new StoreSessionValueMessage();
        ssvMsg.setSessionId(sessionId);
        ssvMsg.setKey(key);
        ssvMsg.setValue(value);
        try {
            PluginController.getCurrentPluginController().processMessage("sessionPlugin", ssvMsg);
        } catch (final PluginException e) {
            logger.error("Unable to store " + key + " for sessionId " + sessionId, e);
        }
    }

}
